<!--
 * @Author: Liz.Zheng
 * @Date: 2021-10-23 10:26:21
 * @LastEditTime: 2022-01-27 16:59:28
 * @LastEditors: Liz.Zheng
 * @Description: 验证码输入框
 * @Motto: Write the code. Change the world.
-->

<template>
  <div class="input-box">
    <div
      class="input-content"
      @keydown="keydown"
      @keyup="keyup"
      @paste="paste"
      @mousewheel="mousewheel"
      @input="inputEvent"
    >
      <input
        max="9"
        min="0"
        maxlength="1"
        data-index="0"
        v-model.trim.number="input[0]"
        ref="input1Ref"
        type="number"
      />
      <input
        max="9"
        min="0"
        maxlength="1"
        data-index="1"
        v-model.trim.number="input[1]"
        type="number"
      />
      <input
        max="9"
        min="0"
        maxlength="1"
        data-index="2"
        v-model.trim.number="input[2]"
        type="number"
      />
      <input
        max="9"
        min="0"
        maxlength="1"
        data-index="3"
        v-model.trim.number="input[3]"
        type="number"
      />
      <input
        max="9"
        min="0"
        maxlength="1"
        data-index="4"
        v-model.trim.number="input[4]"
        type="number"
      />
      <input
        max="9"
        min="0"
        maxlength="1"
        data-index="5"
        v-model.trim.number="input[5]"
        type="number"
      />
    </div>
  </div>
</template>

<script>
import { computed, onMounted, ref, watch } from "vue";
import { message } from "ant-design-vue";
export default {
  name: "CodeInput",
  props: {
    codeValidate: {
      type: Number,
      default: 0,
    },
    clear: {
      type: Number,
      default: 0,
    },
  },
  setup(props, context) {
    //   验证码
    const code = ref([]);
    // 粘贴结果
    const pasteResult = ref("");

    // 输入框内容
    const input = computed(() => {
      if (code.value && Array.isArray(code.value) && code.value.length === 6) {
        return code.value;
      } else if (/^\d{6}$/.test(code.value.toString())) {
        return code.value.toString().split("");
      } else if (pasteResult.value.length === 6) {
        const val = pasteResult.value;
        pasteResult.value = [];
        return val;
      } else {
        return new Array(6);
      }
    });

    // 解决一个输入框输入多个字符
    const inputEvent = (e) => {
      const index = e.target.dataset.index * 1;
      let el = e.target;
      el.value = el.value.replace(/Digit|Numpad/i, "").slice(0, 1);
      input.value[index] = el.value;
    };

    const keydown = (e) => {
      const index = e.target.dataset.index * 1;
      const el = e.target;
      if (e.key === "Backspace") {
        if (input.value[index] && input.value[index].length > 0) {
          input.value[index] = "";
        } else {
          if (el.previousElementSibling) {
            el.previousElementSibling.focus();
            input.value[index - 1] = "";
          }
        }
      } else if (e.key === "Delete") {
        if (input.value[index] && input.value[index].length > 0) {
          input.value[index] = "";
        } else {
          if (el.nextElementSibling) {
            input.value[index - 1] = "";
          }
        }
        if (el.nextElementSibling) {
          el.nextElementSibling.focus();
        }
      } else if (e.key === "Home") {
        el.parentElement.children[0] && el.parentElement.children[0].focus();
      } else if (e.key === "End") {
        el.parentElement.children[input.value.length - 1] &&
          el.parentElement.children[input.value.length - 1].focus();
      } else if (e.key === "ArrowLeft") {
        if (el.previousElementSibling) {
          el.previousElementSibling.focus();
        }
      } else if (e.key === "ArrowRight") {
        if (el.nextElementSibling) {
          el.nextElementSibling.focus();
        }
      } else if (e.key === "ArrowUp") {
        if (input.value[index] * 1 < 9) {
          input.value[index] = (input.value[index] * 1 + 1).toString();
        }
      } else if (e.key === "ArrowDown") {
        if (input.value[index] * 1 > 0) {
          input.value[index] = (input.value[index] * 1 - 1).toString();
        }
      }
    };
    const keyup = (e) => {
      const index = e.target.dataset.index * 1;
      let el = e.target;
      // 解决输入e的问题
      el.value = el.value.replace(/Digit|Numpad/i, "").slice(0, 1);
      if (/Digit|Numpad/i.test(e.code)) {
        // 必须在这里赋值，否则输入框会是空值
        input.value[index] = e.code.replace(/Digit|Numpad/i, "");
        el.nextElementSibling && el.nextElementSibling.focus();
        if (index === 5) {
          if (input.value.join("").length === 6) {
            document.activeElement.blur();
            complete();
          }
        }
      } else {
        if (input.value[index] === "") {
          input.value[index] = "";
        }
      }
    };

    const mousewheel = (e) => {
      const index = e.target.dataset.index;
      if (e.wheelDelta > 0) {
        if (input.value[index] * 1 < 9) {
          input.value[index] = (input.value[index] * 1 + 1).toString();
        }
      } else if (e.wheelDelta < 0) {
        if (input.value[index] * 1 > 0) {
          input.value[index] = (input.value[index] * 1 - 1).toString();
        }
      } else if (e.key === "Enter") {
        if (input.value.join("").length === 6) {
          document.activeElement.blur();
          complete();
        }
      }
    };

    const paste = (e) => {
      e.clipboardData.items[0].getAsString((str) => {
        if (str.toString().length === 6) {
          pasteResult.value = str.split("");
          document.activeElement.blur();
          complete();
        } else {
          // 如果粘贴内容不合规，清除所有内容
          message.warning("请粘贴正确的6位验证码~");
          code.value = new Array(6);
        }
      });
    };

    const getCodeStr = () => {
      for (let key in input.value) {
        if (input.value[key] == "") {
          return false;
        }
      }
      return input.value.join("");
    };

    const complete = () => {
      const codeStr = getCodeStr();
      if (codeStr) {
        context.emit("complete", codeStr);
      } else {
        message.warning("请输入正确的验证码~");
        input1Ref.value.focus();
      }
    };

    watch(
      () => props.codeValidate,
      (val) => {
        complete();
      }
    );

    const input1Ref = ref(null);

    onMounted(() => {
      input1Ref.value.focus();
    });
    watch(
      () => props.clear,
      (val) => {
        code.value = new Array(6);
        input1Ref.value.focus();
      }
    );

    return {
      code,
      input,
      inputEvent,
      keydown,
      keyup,
      mousewheel,
      paste,
      input1Ref,
    };
  },
};
</script>

<style lang="less" scoped>
@size: 45px;
.input-box {
  width: 100%;
  .input-content {
    width: 100%;
    height: @size;
    display: flex;
    align-items: center;
    justify-content: space-between;

    input {
      color: inherit;
      font-family: inherit;
      border: 1px solid #f4f4f4;
      outline: 0;
      height: @size;
      width: @size;
      font-size: 24px;
      text-align: center;
    }
  }

  input::-webkit-outer-spin-button,
  input::-webkit-inner-spin-button {
    appearance: none;
    margin: 0;
  }
}
input::-webkit-outer-spin-button,
input::-webkit-inner-spin-button {
  -webkit-appearance: none;
}

input[type="number"] {
  -moz-appearance: textfield;
}
</style>
